package com.haoqizhe.kernel.activemq.common;

import com.haoqizhe.kernel.activemq.entity.SendParam;
import com.haoqizhe.kernel.activemq.entity.ReceiveParam;
import org.apache.activemq.ScheduledMessage;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.util.StringUtils;

import javax.jms.Destination;
import javax.jms.Session;
import java.util.*;

/**
 * @author haoqizhe.li on 2017/6/21.
 */
public class ActivemqUtil {

    /**
     * 获取消息发送模板
     * @param param template param config
     * @author haoqizhe.li
     * @date 2017/6/12 15:18
     */
    public static JmsTemplate getSendJmsTemplate(SendParam param, JmsTemplate jmsTemplate){

        /**
         *  消息类型   false 为 queue   true为topic
         */
        jmsTemplate.setPubSubDomain(param.isPubSubDomain());

        /**
         *  deliveryMode ,priority ,timeToLive 的开关，要生效，必须配置为true,默认false
         */
        jmsTemplate.setExplicitQosEnabled(true);
        /**
         * 消息优先级
         */
        jmsTemplate.setPriority(param.getPriority());
        /**
         * DeliveryMode.NON_PERSISTENT=1:非持久 ;
         * DeliveryMode.PERSISTENT=2:持久
         */
        jmsTemplate.setDeliveryMode(param.getDeliveryMode());
        /**
         * 消息超时时间
         */
        jmsTemplate.setTimeToLive(param.getTimeToLive());

        /**
         * 开启事务支持 开启之后ACK_MODE参数忽略，默认0
         */
        jmsTemplate.setSessionTransacted(param.isSessionTransacted());

        return jmsTemplate;
    }

    /**
     * 获取消息接收模板
     * @param param,
     * @param jmsTemplate
     * @return org.springframework.jms.core.JmsTemplate
     * @author haoqizhe.li
     * @date 2017/6/27 15:34
     **/
    public static JmsTemplate getReceiveJmsTemplate(ReceiveParam param, JmsTemplate jmsTemplate){

        /**
         * 设置接收消息类型 queue  topic
         */
        jmsTemplate.setPubSubDomain(param.isPubSubDomain());
        /**
         * 是否支持事务
         */
        jmsTemplate.setSessionTransacted(param.isSessionTransacted());
        /**
         * 消息ACK类型
         */
        if(param.isSessionTransacted()){
            jmsTemplate.setSessionAcknowledgeMode(Session.SESSION_TRANSACTED);
        }else{
            jmsTemplate.setSessionAcknowledgeMode(param.getSessionAcknowledgeMode());
        }
        /**
         * 消息接收超时时间
         */
        jmsTemplate.setReceiveTimeout(param.getReceiveTimeout());


        return jmsTemplate;
    }

    /**
     * 从TemplateParam 获取需要发送的消息头
     * @param param 发送消息参数
     * @return org.springframework.messaging.Message
     * @author haoqizhe.li
     * @date 2017/6/21 9:18
     **/
    public static Map<String,Object> getHeaders(SendParam param){

        Map<String,Object> map = new HashMap(0);
        if(!StringUtils.isEmpty(param)){
            /**
             *  消息头设置 消息超时处理机制
             */
            if(!StringUtils.isEmpty(param.getTimeOverDo())){
                map.put(ActivemqConstant.MessageHeadersParam.TIME_OVER_DO,param.getTimeOverDo());
            }
            /**
             *  消息超时后 需重新发送消息的次数
             */
            if(param.getResendTime() > 0){
                map.put(ActivemqConstant.MessageHeadersParam.RESEND_TIME,param.getResendTime());
            }
            /**
             * 消息延迟发送时间
             */
            if(param.getScheduledDelay() > 0){
                map.put(ScheduledMessage.AMQ_SCHEDULED_DELAY,param.getScheduledDelay());
            }
            /**
             * 消息重复发送次数
             */
            if(param.getScheduledRepeat() > 0){
                map.put(ScheduledMessage.AMQ_SCHEDULED_REPEAT,param.getScheduledRepeat());
            }
            /**
             * 消息重复发送间隔时间
             */
            if(param.getScheduledPeriod() > 0){
                map.put(ScheduledMessage.AMQ_SCHEDULED_PERIOD,param.getScheduledPeriod());
            }
            /**
             *  消息定时发送
             */
            if(!StringUtils.isEmpty(param.getScheduledCron())){
                map.put(ScheduledMessage.AMQ_SCHEDULED_CRON,param.getScheduledCron());
            }
            /**
             * 消息转发
             */
            if(!StringUtils.isEmpty(param.getReplyTo())){
                map.put(ActivemqConstant.MessageHeadersParam.REPLY_TO,param.getReplyTo());
                map.put(ActivemqConstant.MessageHeadersParam.REPLY_TYPE,StringUtils.isEmpty(param.getReplyType())? ActivemqConstant.DestinationType.QUEUE:param.getReplyType());
                map.put(ActivemqConstant.MessageHeadersParam.CORRELATION_ID,StringUtils.isEmpty(param.getCorrelationId())?UUID.randomUUID().toString():param.getCorrelationId());
            }
            if(!StringUtils.isEmpty(param.getLogId())){
                map.put(ActivemqConstant.MessageHeadersParam.LOG_ID,param.getLogId());
            }

            /**
             * 自定义消息头
             */
            Map<String,Object> headers = param.getHeaders();
            if(!StringUtils.isEmpty(headers)){
                for(Map.Entry<String, Object> entry : headers.entrySet()){
                    map.put(entry.getKey(),entry.getValue());
                }
            }
        }
        return map;
    }

    /**
     *  获取消息目的地
     * @param sendParam 发送消息参数
     * @param destinationPrefix 目的地前缀
     * @return javax.jms.Destination
     * @author haoqizhe.li
     * @date 2017/7/13 22:39
     */
    public static Destination getDestination(SendParam sendParam,String destinationPrefix){
        return getDestination(sendParam.getDestinationName(),destinationPrefix,sendParam.isDestinationPrefix(),sendParam.isPubSubDomain(),sendParam.isVirtualTopic());
    }


    /**
     *  获取消息目的地
     * @param destinationName, 目的地名称
     * @param destinationPrefix, 目的地前缀
     * @param  isDestinationPrefix, 是否添加前缀
     * @param  pubSubDomain 消息类型 true ：topic ，false ：queue
     * @return javax.jms.Destination
     * @author haoqizhe.li
     * @date 2017/7/13 22:39
     **/
    public static Destination getDestination(String destinationName,String destinationPrefix,boolean isDestinationPrefix,boolean pubSubDomain,boolean isVirtualTopic){

        String dn = getDestinationName(destinationName,destinationPrefix,isDestinationPrefix,pubSubDomain);

        Destination destination = null;

        if(pubSubDomain){
            /**
             * 设置虚拟主题并且用户传入的目的地名称不是Virtual.开头时自动添加Virtual前缀
             */
            if(isVirtualTopic && !dn.startsWith(ActivemqConstant.DestinationPrefix.VIRTUAL_TOPIC) && !dn.startsWith(ActivemqConstant.DestinationPrefix.TOPIC_PREFIX)){
                dn = ActivemqConstant.DestinationPrefix.VIRTUAL_TOPIC + dn;
            }else if(isVirtualTopic && dn.startsWith(ActivemqConstant.DestinationPrefix.TOPIC_PREFIX)){
                dn = ActivemqConstant.DestinationPrefix.TOPIC_PREFIX+ActivemqConstant.DestinationPrefix.VIRTUAL_TOPIC + dn.replace(ActivemqConstant.DestinationPrefix.TOPIC_PREFIX,"");
            }
            destination = new ActiveMQTopic(dn);
        }else{
            destination = new ActiveMQQueue(dn);
        }

        return destination;
    }
    /**
     * 出来目的地名称，是否添加目的地前缀，添加何种前缀
     * @param destinationName, 目的地名称
     * @param destinationPrefix 目的地前缀
     * @param isDestinationPrefix 是否要添加目的地前缀
     * @return java.lang.String
     * @author haoqizhe.li
     * @date 2017/7/5 17:48
     **/
    private static String getDestinationName(String destinationName,String destinationPrefix,boolean isDestinationPrefix,boolean pubSubDomain){

        String desName = "";

        if(isDestinationPrefix){
            if(!StringUtils.isEmpty(destinationPrefix)){
                if(destinationName.indexOf(",") > -1){
                    String[] names = destinationName.split(",");

                    for(String name : names){
                        desName += doPrefix(name,destinationPrefix,pubSubDomain) + ",";
                    }

                    desName = desName.substring(0,desName.length()-1);
                }else{
                    desName = doPrefix(destinationName,destinationPrefix,pubSubDomain);
                }
            }else{
                desName = destinationName;
            }
        }else{
            desName = destinationName;
        }

        return desName;
    }
    /**
     * 需要添加业务系统目的地前缀destination prefix时 对 参数 name的处理
     *                activemq的特性，目的地名称可前缀：VirtualTopic.   虚拟主题
     *                                                  topic://   主题
     *                                                  queue://   队列
     * @param name 目的地名称
     * @param destinationPrefix 目的地前缀
     * @return java.lang.String
     *         eg: 1  param[name:VirtualTopic.test,destinationPrefix:client]
     *             return[VirtualTopic.test]
     *             2  param[name:topic://test,destinationPrefix:client]
     *             return[topic://client.test]
     *             3  param[name:queue://test,destinationPrefix:client]
     *             return[queue://client.test]
     * @author haoqizhe.li
     * @date 2017/7/5 17:49
     **/
    private static String doPrefix(String name,String destinationPrefix,boolean pubSubDomain){

        String destinationName = "";

        if(pubSubDomain && name.startsWith(ActivemqConstant.DestinationPrefix.VIRTUAL_TOPIC)){
                destinationName = ActivemqConstant.DestinationPrefix.VIRTUAL_TOPIC+
                        destinationPrefix+"."+name.replace(ActivemqConstant.DestinationPrefix.VIRTUAL_TOPIC,"") ;
        }else if(name.startsWith(ActivemqConstant.DestinationPrefix.QUEUE_PREFIX) && !pubSubDomain){
            destinationName = ActivemqConstant.DestinationPrefix.QUEUE_PREFIX +
                    destinationPrefix +"."+ name.replace(ActivemqConstant.DestinationPrefix.QUEUE_PREFIX,"") ;
        }else if(name.startsWith(ActivemqConstant.DestinationPrefix.TOPIC_PREFIX) && pubSubDomain){
            destinationName = ActivemqConstant.DestinationPrefix.TOPIC_PREFIX +
                    destinationPrefix +"."+ name.replace(ActivemqConstant.DestinationPrefix.TOPIC_PREFIX,"") ;
        }else{
            destinationName = destinationPrefix + "."+name;
        }

        return destinationName;
    }

}
